//Example of delegating to a map and creating some methods in methodMissing.
//In real app we'd probably have to do some syncrhonizing there.
//Note that if we override methodMissing we need to do some extra work
//inside methodMissing to have our getProperty() called on getters.

ExpandoMetaClass.enableGlobally() 

class Manager{

   def map

   //If we did a simple 
   //def tangerine 
   //here, our getProperty would need to explicilty route to it.
   private tangerine = 'tasty fruit'
   def tangerine(){return tangerine}

  def getProperty(String str){ 
      //def obj = super.getProperty(str)
      //if(obj != null)
        // return obj
     /* if(str == 'tangerine'){
         println tangerine
         return tangerine
      }*/
      return map[str]
  }


   def methodMissing(String name, args){
       println "intercepting " + name
       //This is the extra work we need to do to get our getProperty() called for getters
       if(name.startsWith("get")){
          def key = name - "get"
          key =  key[0].toLowerCase() + key.substring(1)
          return getProperty(key)
       }
      
       if(name.startsWith("simple")){
            Manager.metaClass."${name}" = {Object[] varArgs ->
                return "simple from existing method"
            }
            return this."${name}"(args)

            //return 'simple from methodMissing'
            
       }

       if(name.startsWith("doWhatYouSent")){
            def clos =  {Object[] varArgs ->
                return varArgs[0]
            }
            Manager.metaClass."${name}" = clos

            return clos(args)
            
       }

   }

}

def man = new Manager()
man.map = ['hi': 'there']

assert 'simple from existing method' ==  man.simpleStuff()
//Not tested, but note that we don't see the 'interceping' message here,  because by this
//time we've created a method.
assert 'simple from existing method' ==  man.simpleStuff()

//??Doesn't knock out the methods we added!!
//That is, when we make this call, we don't see the 'intercepting' message
//GroovySystem.metaClassRegistry.removeMetaClass(Manager.class)
//println "After removing metaClass " +  man.simpleStuff()

assert "yyy" ==  man.doWhatYouSent("yyy")

//Trying to hit the map that the manager is delegating to, this time with standard method access syntax
assert "there" == man.getHi()
//And this time with the shortened syntax that looks like property access syntax but is really method access syntax
assert "there" ==  man.hi

assert 'tasty fruit' == man.tangerine()

